#include "common.h"

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("%d",sockfd);
    myAssert(sockfd != -1, "socket error");
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = INADDR_ANY;
    local.sin_port = htons(8080);
    // 绑定
    myAssert(bind(sockfd, (sockaddr *)&local, sizeof(local)) != -1, "bind error");
    // 监听
    myAssert(listen(sockfd, SOMAXCONN) != -1, "listen error");
    // 接收
    // 创建一个epoll文件描述符并返回
    int epfd = epoll_create1(0);
    myAssert(epfd != -1, "epoll_create1 error");
    // 设置结构体epoll_event
    struct epoll_event events[MAX_EVENTS], ev;
    ev.events = EPOLLIN|EPOLLET;
    ev.data.fd = sockfd;
    setnonblocking(sockfd);
    // 开始先把sockfd加进去
    epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
    while (true)
    {
        int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); // 有nfds个fd发生事件
        std::cout<<nfds<<std::endl;
        for (int i = 0; i < nfds; i++)                       // 处理事件
        {
            if (events[i].data.fd == sockfd) // 如果是sockfd被触发，表示有新客户端连接
            {
                struct sockaddr_in cli_addr;
                bzero(&cli_addr, sizeof(cli_addr));
                socklen_t len = sizeof(cli_addr);
                int cli_sock = accept(sockfd, (sockaddr *)&cli_addr, &len);
                myAssert(cli_sock != -1, "accept error");
                // 这个时候相当于sockfd从epoll里拿出来，再加进去
                bzero(&ev,sizeof(ev));
                ev.data.fd = cli_sock;
                ev.events = EPOLLIN | EPOLLET; // ET模式,支持更多并发
                // ET模式需要非阻塞socket
                setnonblocking(cli_sock);
                epoll_ctl(epfd, EPOLL_CTL_ADD, cli_sock, &ev);
                // 打印IP,PORT
                printf("new client fd: %d! IP: %s Port: %d\n",
                       cli_sock, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
            }
            else if (events[i].events & EPOLLIN)
            {
                while (true)
                {
                    int cli_sock=events[i].data.fd;
                    char buf[BUFFER_NUM]; // 缓冲区
                    bzero(buf, BUFFER_NUM);
                    ssize_t read_bytes = read(cli_sock, buf, BUFFER_NUM);
                    if (read_bytes > 0)
                    {
                        buf[read_bytes] = 0;
                        printf("message from client fd %d : %s \n", cli_sock, buf);
                        write(cli_sock, buf, strlen(buf));
                    }
                    else if (read_bytes == -1&& errno == EINTR)                   
                    {
                        //客户端正常中断,继续读取
                        printf("continue reading\n");
                        continue;
                    }
                    else if(read_bytes==-1&&((errno==EAGAIN)||(errno == EWOULDBLOCK)))
                    {
                        //fd上的数据全部读取完毕
                        printf("finish read\n");
                        break;
                    }
                    else if(read_bytes==0)
                    {
                        // read error ,read more times
                        printf("fd disconnected:%d \n",cli_sock);
                        close(cli_sock);
                        break;
                    }
                }
            }
            else
            {
                //
                
            }
        }
    }
    printf("close sockfd\n");
    close(sockfd);
    return 0;
}